// SPDX-FileCopyrightText: Copyright 2025-2025 深圳市同心圆网络有限公司
// SPDX-License-Identifier: Apache-2.0

package resource_exam_api_serv

import (
	"context"
	"time"

	"gitcode.com/lvupclub/lvup-api/dao"
	"gitcode.com/lvupclub/lvup-api/dao/resource_dao"
	"gitcode.com/lvupclub/proto-gen-go.git/src/resource_api"
	"gitcode.com/lvupclub/proto-gen-go.git/src/resource_exam_api"
	"gitcode.com/lvupclub/proto-gen-go.git/src/resource_exam_type_api"
	"github.com/google/uuid"
	"google.golang.org/protobuf/proto"
	"google.golang.org/protobuf/types/known/anypb"
)

func (apiImpl *ResourceExamApiImpl) Create(ctx context.Context, req *resource_exam_api.CreateRequest) (*resource_exam_api.CreateResponse, error) {
	sessItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &resource_exam_api.CreateResponse{
			Code:   resource_exam_api.CreateResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	resourceItem, err := resource_dao.ResourceInfoDao.Get(ctx, req.ResourceId)
	if err != nil {
		return &resource_exam_api.CreateResponse{
			Code:   resource_exam_api.CreateResponse_CODE_NO_RESOURCE,
			ErrMsg: "资料库不存在",
		}, nil
	}
	if resourceItem.ResourceType != resource_api.RESOURCE_TYPE_RESOURCE_TYPE_EXAM || resourceItem.OwnerUserId != sessItem.UserId {
		return &resource_exam_api.CreateResponse{
			Code:   resource_exam_api.CreateResponse_CODE_NO_RESOURCE,
			ErrMsg: "资料库不存在",
		}, nil
	}

	questionData, err := proto.Marshal(req.BasicInfo.Question)
	if err != nil {
		return nil, err
	}

	questionId := uuid.NewString()
	nowTime := time.Now().UnixMilli()

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx context.Context) (interface{}, error) {
		err = resource_dao.QuestionInfoDao.IncIndex(sessCtx, req.ResourceId, req.QuestionIndex)
		if err != nil {
			return nil, err
		}
		err = resource_dao.QuestionInfoDao.Insert(sessCtx, &resource_dao.QuestionInfoDbItem{
			QuestionId:    questionId,
			ResourceId:    req.ResourceId,
			QuestionIndex: req.QuestionIndex,
			BasicInfo: resource_dao.BasicQuestionInfoDbItem{
				QuestionData: questionData,
			},
			CreateTime: nowTime,
			UpdateTime: nowTime,
		})
		if err != nil {
			return nil, err
		}
		return &resource_exam_api.CreateResponse{
			Code:       resource_exam_api.CreateResponse_CODE_OK,
			QuestionId: questionId,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	return ret.(*resource_exam_api.CreateResponse), nil
}

func (apiImpl *ResourceExamApiImpl) UpdateBasic(ctx context.Context, req *resource_exam_api.UpdateBasicRequest) (*resource_exam_api.UpdateBasicResponse, error) {
	sessItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &resource_exam_api.UpdateBasicResponse{
			Code:   resource_exam_api.UpdateBasicResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	resourceItem, err := resource_dao.ResourceInfoDao.Get(ctx, req.ResourceId)
	if err != nil {
		return &resource_exam_api.UpdateBasicResponse{
			Code:   resource_exam_api.UpdateBasicResponse_CODE_NO_RESOURCE,
			ErrMsg: "资料库不存在",
		}, nil
	}
	if resourceItem.ResourceType != resource_api.RESOURCE_TYPE_RESOURCE_TYPE_EXAM || resourceItem.OwnerUserId != sessItem.UserId {
		return &resource_exam_api.UpdateBasicResponse{
			Code:   resource_exam_api.UpdateBasicResponse_CODE_NO_RESOURCE,
			ErrMsg: "资料库不存在",
		}, nil
	}
	questionItem, err := resource_dao.QuestionInfoDao.Get(ctx, req.ResourceId, req.QuestionId)
	if err != nil {
		return &resource_exam_api.UpdateBasicResponse{
			Code:   resource_exam_api.UpdateBasicResponse_CODE_NO_QUESTION,
			ErrMsg: "问题不存在",
		}, nil
	}
	question, err := questionItem.ToQuestionInfo()
	if err != nil {
		return nil, err
	}
	if question.BasicInfo.Question.TypeUrl != req.BasicInfo.Question.TypeUrl {
		return &resource_exam_api.UpdateBasicResponse{
			Code:   resource_exam_api.UpdateBasicResponse_CODE_WRONG_DATA,
			ErrMsg: "错误的请求参数",
		}, nil
	}

	questionData, err := proto.Marshal(req.BasicInfo.Question)
	if err != nil {
		return nil, err
	}

	nowTime := time.Now().UnixMilli()

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx context.Context) (interface{}, error) {
		err = resource_dao.QuestionInfoDao.UpdateBasic(sessCtx, req.ResourceId, req.QuestionId, &resource_dao.BasicQuestionInfoDbItem{
			QuestionData: questionData,
		}, nowTime)
		if err != nil {
			return nil, err
		}
		return &resource_exam_api.UpdateBasicResponse{
			Code: resource_exam_api.UpdateBasicResponse_CODE_OK,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	return ret.(*resource_exam_api.UpdateBasicResponse), nil
}

func (apiImpl *ResourceExamApiImpl) UpdateIndex(ctx context.Context, req *resource_exam_api.UpdateIndexRequest) (*resource_exam_api.UpdateIndexResponse, error) {
	sessItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &resource_exam_api.UpdateIndexResponse{
			Code:   resource_exam_api.UpdateIndexResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	resourceItem, err := resource_dao.ResourceInfoDao.Get(ctx, req.ResourceId)
	if err != nil {
		return &resource_exam_api.UpdateIndexResponse{
			Code:   resource_exam_api.UpdateIndexResponse_CODE_NO_RESOURCE,
			ErrMsg: "资料库不存在",
		}, nil
	}
	if resourceItem.ResourceType != resource_api.RESOURCE_TYPE_RESOURCE_TYPE_EXAM || resourceItem.OwnerUserId != sessItem.UserId {
		return &resource_exam_api.UpdateIndexResponse{
			Code:   resource_exam_api.UpdateIndexResponse_CODE_NO_RESOURCE,
			ErrMsg: "资料库不存在",
		}, nil
	}
	exist, err := resource_dao.QuestionInfoDao.Exist(ctx, req.ResourceId, req.QuestionId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &resource_exam_api.UpdateIndexResponse{
			Code:   resource_exam_api.UpdateIndexResponse_CODE_NO_QUESTION,
			ErrMsg: "问题不存在",
		}, nil
	}

	nowTime := time.Now().UnixMilli()

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx context.Context) (interface{}, error) {
		err = resource_dao.QuestionInfoDao.IncIndex(sessCtx, req.ResourceId, req.QuestionIndex)
		if err != nil {
			return nil, err
		}
		err = resource_dao.QuestionInfoDao.UpdateIndex(sessCtx, req.ResourceId, req.QuestionId, req.QuestionIndex, nowTime)
		if err != nil {
			return nil, err
		}
		return &resource_exam_api.UpdateIndexResponse{
			Code: resource_exam_api.UpdateIndexResponse_CODE_OK,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	return ret.(*resource_exam_api.UpdateIndexResponse), nil
}

func (apiImpl *ResourceExamApiImpl) Remove(ctx context.Context, req *resource_exam_api.RemoveRequest) (*resource_exam_api.RemoveResponse, error) {
	sessItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &resource_exam_api.RemoveResponse{
			Code:   resource_exam_api.RemoveResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	resourceItem, err := resource_dao.ResourceInfoDao.Get(ctx, req.ResourceId)
	if err != nil {
		return &resource_exam_api.RemoveResponse{
			Code:   resource_exam_api.RemoveResponse_CODE_NO_RESOURCE,
			ErrMsg: "资料库不存在",
		}, nil
	}
	if resourceItem.ResourceType != resource_api.RESOURCE_TYPE_RESOURCE_TYPE_EXAM || resourceItem.OwnerUserId != sessItem.UserId {
		return &resource_exam_api.RemoveResponse{
			Code:   resource_exam_api.RemoveResponse_CODE_NO_RESOURCE,
			ErrMsg: "资料库不存在",
		}, nil
	}
	exist, err := resource_dao.QuestionInfoDao.Exist(ctx, req.ResourceId, req.QuestionId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &resource_exam_api.RemoveResponse{
			Code: resource_exam_api.RemoveResponse_CODE_OK,
		}, nil
	}

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx context.Context) (interface{}, error) {
		err = resource_dao.QuestionInfoDao.Remove(sessCtx, req.ResourceId, req.QuestionId)
		if err != nil {
			return nil, err
		}
		err = resource_dao.QuestionStateDao.RemoveByQuestion(sessCtx, req.ResourceId, req.QuestionId)
		if err != nil {
			return nil, err
		}
		return &resource_exam_api.RemoveResponse{
			Code: resource_exam_api.RemoveResponse_CODE_OK,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	return ret.(*resource_exam_api.RemoveResponse), nil
}

func (apiImpl *ResourceExamApiImpl) List(ctx context.Context, req *resource_exam_api.ListRequest) (*resource_exam_api.ListResponse, error) {
	emptyList := []*resource_exam_api.QuestionInfo{}

	sessItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &resource_exam_api.ListResponse{
			Code:         resource_exam_api.ListResponse_CODE_WRONG_SESSION,
			ErrMsg:       "会话不存在",
			QuestionList: emptyList,
		}, nil
	}
	resourceItem, err := resource_dao.ResourceInfoDao.Get(ctx, req.ResourceId)
	if err != nil {
		return &resource_exam_api.ListResponse{
			Code:         resource_exam_api.ListResponse_CODE_NO_RESOURCE,
			ErrMsg:       "资料库不存在",
			QuestionList: emptyList,
		}, nil
	}
	if resourceItem.ResourceType != resource_api.RESOURCE_TYPE_RESOURCE_TYPE_EXAM || resourceItem.OwnerUserId != sessItem.UserId {
		return &resource_exam_api.ListResponse{
			Code:         resource_exam_api.ListResponse_CODE_NO_RESOURCE,
			ErrMsg:       "资料库不存在",
			QuestionList: emptyList,
		}, nil
	}
	questionItemList, err := resource_dao.QuestionInfoDao.List(ctx, req.ResourceId)
	if err != nil {
		return nil, err
	}
	//生成结果
	answer, err := anypb.New(&resource_exam_type_api.EmptyAnswer{})
	if err != nil {
		return nil, err
	}
	questionList := []*resource_exam_api.QuestionInfo{}
	for _, questionItem := range questionItemList {
		question, err := questionItem.ToQuestionInfo()
		if err != nil {
			continue
		}
		question.Answer = answer
		questionList = append(questionList, question)
	}
	return &resource_exam_api.ListResponse{
		Code:         resource_exam_api.ListResponse_CODE_OK,
		QuestionList: questionList,
	}, nil
}

func (apiImpl *ResourceExamApiImpl) Get(ctx context.Context, req *resource_exam_api.GetRequest) (*resource_exam_api.GetResponse, error) {
	emptyAny, err := anypb.New(&resource_exam_type_api.EmptyAnswer{})
	if err != nil {
		return nil, err
	}

	emptyInfo := &resource_exam_api.QuestionInfo{
		BasicInfo: &resource_exam_api.BasicQuestionInfo{
			Question: emptyAny,
		},
		Answer: emptyAny,
	}

	sessItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &resource_exam_api.GetResponse{
			Code:     resource_exam_api.GetResponse_CODE_WRONG_SESSION,
			ErrMsg:   "会话不存在",
			Question: emptyInfo,
		}, nil
	}
	resourceItem, err := resource_dao.ResourceInfoDao.Get(ctx, req.ResourceId)
	if err != nil {
		return &resource_exam_api.GetResponse{
			Code:     resource_exam_api.GetResponse_CODE_NO_RESOURCE,
			ErrMsg:   "资料库不存在",
			Question: emptyInfo,
		}, nil
	}
	if resourceItem.ResourceType != resource_api.RESOURCE_TYPE_RESOURCE_TYPE_EXAM || resourceItem.OwnerUserId != sessItem.UserId {
		return &resource_exam_api.GetResponse{
			Code:     resource_exam_api.GetResponse_CODE_NO_RESOURCE,
			ErrMsg:   "资料库不存在",
			Question: emptyInfo,
		}, nil
	}

	questionItem, err := resource_dao.QuestionInfoDao.Get(ctx, req.ResourceId, req.QuestionId)
	if err != nil {
		return &resource_exam_api.GetResponse{
			Code:     resource_exam_api.GetResponse_CODE_NO_QUESTION,
			ErrMsg:   "问题不存在",
			Question: emptyInfo,
		}, nil
	}
	question, err := questionItem.ToQuestionInfo()
	if err != nil {
		return nil, err
	}
	question.Answer = emptyAny

	return &resource_exam_api.GetResponse{
		Code:     resource_exam_api.GetResponse_CODE_OK,
		Question: question,
	}, nil
}
